package com.xframework.security.service;

import com.alibaba.fastjson.JSON;
import com.xframework.Base;
import com.xframework.exception.BusinessException;
import com.xframework.exception.ExceptionCode;
import com.xframework.redis.XRedisTemplate;
import com.xframework.remote.HttpClient;
import com.xframework.security.api.WxRpcService;
import com.xframework.security.model.WxMessageTemplateSend;
import com.xframework.security.model.WxSend;
import com.xframework.security.model.WxSendText;
import com.xframework.security.util.Constant;
import com.xframework.security.util.DigestUtil;
import com.xframework.security.util.WxConstant;
import com.xframework.service.BaseService;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.http.HttpServletRequest;
import java.security.MessageDigest;
import java.text.MessageFormat;
import java.util.*;

@DubboService
@Component
public class WxService extends BaseService implements WxRpcService {

    @Override
    public String getWxGlobalAccessToken() {
        try {
            String accessToken = XRedisTemplate.get(WxConstant.WX_GLOBAL_ACCESS_TOKEN_ + WxConstant.wxAppId);
            if (accessToken == null) {
                Map<String, Object> accessTokenMap = HttpClient.httpsRequestJson(MessageFormat.format(WxConstant.WX_GLOBAL_ACCESS_TOKEN_URL, WxConstant.wxAppId, WxConstant.wxAppSecret), RequestMethod.GET.name(), null);
                Object errmsg = accessTokenMap.get("errmsg");
                if (errmsg != null) {
                    throw new BusinessException(errmsg.toString());
                }
                accessToken = accessTokenMap.get(WxConstant.ACCESS_TOKEN).toString();
                XRedisTemplate.setString(WxConstant.WX_GLOBAL_ACCESS_TOKEN_ + WxConstant.wxAppId, accessToken, 7000);
            }
            return accessToken;
        } catch (Exception e) {
            throw new BusinessException(e.getMessage(), e);
        }
    }

    @Override
    public Map<String, Object> getWxWebAccessToken(HttpServletRequest request) {
        try {
            String echostr = request.getParameter("echostr");
            if (echostr == null) {
                String code = request.getParameter("code");
                if (code != null) {
                    String wxWebAccessTokenUrl = MessageFormat.format(WxConstant.WX_WEB_ACCESS_TOKEN_URL, WxConstant.wxAppId, WxConstant.wxAppSecret, code);
                    Map<String, Object> wxWebAccessTokenMap = HttpClient.httpsRequestJson(wxWebAccessTokenUrl, RequestMethod.GET.name(), null);
                    return wxWebAccessTokenMap;
                } else {
                    throw new BusinessException("code is null");
                }
            } else {
                throw new BusinessException("echostr is null");
            }
        } catch (Exception e) {
            throw new BusinessException(e.getMessage(), e);
        }
    }

    @Override
    public String getWxJsApiTicket() {
        try {
            String jsApiTicket = XRedisTemplate.get(WxConstant.WX_JS_API_TICKET_ + WxConstant.wxAppId);
            if (jsApiTicket == null) {
                String accessToken = this.getWxGlobalAccessToken();
                String wxJsApiTicketUrl = MessageFormat.format(WxConstant.WX_JS_API_TICKET_URL, accessToken);
                Map<String, Object> jsApiTicketMap = HttpClient.httpsRequestJson(wxJsApiTicketUrl, RequestMethod.GET.name(), null);
                String errmsg = jsApiTicketMap.get("errmsg").toString();
                if (!errmsg.equals("ok")) {
                    throw new BusinessException(errmsg.toString());
                }
                jsApiTicket = jsApiTicketMap.get(WxConstant.TICKET).toString();
                XRedisTemplate.setString(WxConstant.WX_JS_API_TICKET_ + WxConstant.wxAppId, jsApiTicket, 7000);
            }
            return jsApiTicket;
        } catch (Exception e) {
            throw new BusinessException(e.getMessage(), e);
        }
    }

    @Override
    public Map<String, Object> getUserInfoByTokenOpenId(String accessToken, String openid) {
        try {
            String wxUserInfoUrl = MessageFormat.format(WxConstant.WX_USERINFO_URL, accessToken, openid);
            Map<String, Object> userInfoMap = HttpClient.httpsRequestJson(wxUserInfoUrl, RequestMethod.GET.name(), null);
            XRedisTemplate.setObject(WxConstant.WX_OPENID_ + openid, userInfoMap, 7000);
            return userInfoMap;
        } catch (Exception e) {
            throw new BusinessException(e.getMessage(), e);
        }
    }

    @Override
    public Map<String, String> getWxConfig(String url) {
        try {
            String jsApiTicket = this.getWxJsApiTicket();
            String nonceStr = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
            String timeStamp = String.valueOf(System.currentTimeMillis() / 1000);
            String str = "jsapi_ticket=" + jsApiTicket + "&noncestr=" + nonceStr + "&timestamp=" + timeStamp + "&url=" + url;
//            String signature = DigestUtils.sha1Hex(str);
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(str.getBytes("UTF-8"));
            String signature = DigestUtil.byteToHex(crypt.digest());
            Map<String, String> wxConfig = new HashMap<String, String>();
            wxConfig.put("appId", WxConstant.wxAppId);
            wxConfig.put("timestamp", timeStamp);
            wxConfig.put("nonceStr", nonceStr);
            wxConfig.put("signature", signature);
            return wxConfig;
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0000, e);
        }
    }

    @Override
    public void sendWxMessageByUserIds(String openId, String content) {
        try {
            if (openId != null) {
                this.sendWxMessageByOpenId(openId, content);
            }
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0000, e);
        }
    }

    @Override
    public void sendWxTemplateMessageByUserIds(String openId, String redirectUrl, String templateId, Map<String, Map<String, String>> data) {
        try {
            if (openId != null) {
                System.out.println("openId====" + openId);
                this.sendWxTemplateMessageByOpenId(openId, redirectUrl, templateId, data);
            }
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0000, e);
        }
    }

    @Override
    public String sendWxMessageByOpenId(String openId, String content) {
        try {
            String accessToken = this.getWxGlobalAccessToken();
            String wxSendUrl = MessageFormat.format(WxConstant.WX_SEND_URL, accessToken);
            WxSend wxSend = new WxSend(openId, "text", new WxSendText(content));
            String wxSendJson = JSON.toJSONString(wxSend);
            String wxSendResult = HttpClient.doPostJson(wxSendUrl, wxSendJson);
            System.out.println(openId + "==" + content + "==" + wxSendResult);
            return wxSendResult;
        } catch (Exception e) {
            throw new BusinessException(e.getMessage(), e);
        }
    }

    @Override
    public String sendWxTemplateMessageByOpenId(String openId, String redirectUrl, String templateId, Map<String, Map<String, String>> data) {
        try {
            String accessToken = this.getWxGlobalAccessToken();
            String wxSendUrl = MessageFormat.format(WxConstant.WX_TEMPLATE_URL, accessToken);
            WxMessageTemplateSend wxMessageTemplateSend = new WxMessageTemplateSend(openId, redirectUrl, templateId, data);
            String wxSendJson = JSON.toJSONString(wxMessageTemplateSend);
            String wxSendResult = HttpClient.doPostJson(wxSendUrl, wxSendJson);
            return wxSendResult;
        } catch (Exception e) {
            throw new BusinessException(e.getMessage(), e);
        }
    }

    @Override
    public String genRandomCode(String mobile, int length) {
        StringBuffer stringBuffer = new StringBuffer(Base.BLANK);
        Random random = new Random();
        for (int i = 0; i < length; i++) {
            stringBuffer.append(random.nextInt(10));
        }
        String verifyCode = stringBuffer.toString();
        XRedisTemplate.setString(Constant.SECURITY_RANDOM_ + mobile, verifyCode, 60);
        return verifyCode;
    }


    public static void main(String[] args) {
        String json = JSON.toJSONString("22_y-oJs7PyJRv5muMK1CJFN8zkHU5n2_xOwduyn1ROCddf41FgBP3whR6XMpJekAIUEHMLKp37OKGD5s3HLT3hE8STBTlJ8RM_F23biflDE-vsTtHsyELk11R2Rk5hQonVCU4mY_dHKqif857FGFUfADABAP");
        System.out.println(json);
        String[] arr = {"noncestr=", "timestamp=", "jsapi_ticket=", "url="};
        Arrays.sort(arr);
        for (String s : arr) {
            System.out.println(s);
        }
    }
}
